import {
  BeforeUpdate,
  CreateDateColumn,
  UpdateDateColumn,
  PrimaryColumn,
  BeforeInsert,
  PrimaryGeneratedColumn,
  Column,
  DeleteDateColumn,
} from 'typeorm';
import { customAlphabet, urlAlphabet } from 'nanoid';
export type Class<T = object, A extends unknown[] = unknown[]> = new (
  ...args: A
) => T;

function mixinStringId<T extends Class<{}, any[]>>(base: T) {
  class Derived extends base {
    @PrimaryColumn('varchar')
    id: string;

    @BeforeInsert()
    generateId() {
      if (!this.id) {
        this.id = customAlphabet(urlAlphabet, 16)();
      }
    }
  }
  return Derived;
}
function mixinUuId<T extends Class<{}, any[]>>(base: T) {
  class Derived extends base {
    @PrimaryGeneratedColumn('uuid')
    id: string;
  }
  return Derived;
}
function mixinDelete<T extends Class<{}, any[]>>(base: T) {
  class Derived extends base {
    @Column({ default: false })
    isDelete: boolean;
  }
  return Derived;
}
export class BaseEntity {
  @CreateDateColumn()
  createdAt: Date;

  @DeleteDateColumn()
  deletedAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @BeforeUpdate()
  setUpdateDate(): void {
    this.updatedAt = new Date();
  }
}
export const WithStringId = mixinStringId(BaseEntity);
export const WithUuid = mixinUuId(BaseEntity);
export const WithDelete = mixinDelete(BaseEntity);
